package com.etlmaster.executor.steps.func;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.etlmaster.executor.Step;
import com.etlmaster.executor.StepMeta;
import com.etlmaster.executor.annotation.StepInstruction;
import com.etlmaster.executor.utils.StepState;
import com.etlmaster.jdbc.JdbcTemplate;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import org.apache.commons.net.telnet.TelnetClient;

/**
 * @author Wugf
 * @date 2016-03-08
 */
@StepInstruction("telnet")
public class TelnetStep extends Step {
	private TelnetStepMeta meta;
	private static Map hostInfo;
	private String command;
	private String result=""; 
	
	
	  TelnetClient client = new TelnetClient("vt52");
	  JSch jsch=new JSch();
	  Session session;
	  Channel channel;
	  
      StringBuffer buffer = new StringBuffer();
      
      InputStream inputStream = null;        //输入流,接收服务端的返回信息
      OutputStream outputStream = null;        //输出流,向服务端写命令
      private static List<String> defaultPromt = new ArrayList<String>();
      private static List<String> user = new ArrayList<String>();
      private static List<String> pass = new ArrayList<String>();
      
    static {
        defaultPromt.add("#");
        defaultPromt.add(">");
        user.add("ogin:");
        pass.add("assword:");
    }
    
	public TelnetStep(StepMeta meta) {
		super(meta);
		this.meta=(TelnetStepMeta)meta;
		// TODO Auto-generated constructor stub
	}

    
    
    
    public void sendCommand(String command) throws Exception {
        sendCommand(command, defaultPromt);
    }
    
    /**
     * 往服务器输入命令
     * @param command        命令指令
     * @param wantedEndString
     * @throws Exception
     */
    public void sendCommand(String command, List<String> wantedEndString)
                    throws Exception {
            waitForString(wantedEndString);
            this.buffer.delete(0, this.buffer.length());
            //输出输入的命令值
//            System.out.println(command + "\n");
            this.outputStream.write((command + "\n").getBytes());
            this.outputStream.flush();
    }
    public String getResult(List<String> endString) throws Exception {
        waitForString(endString);
        return this.buffer.toString();
}

private void waitForString(List<String> wantedEndString) throws Exception {
        int aword = 0;
        boolean matchOne = false;
        while (!(matchOne)) {
                for (int i = 0; i < wantedEndString.size(); ++i) {
                        if ((this.buffer.toString().trim()
                                        .endsWith((String) wantedEndString.get(i)))
                                        && (this.inputStream.available() == 0)) {
                                matchOne = true;
                        }
                }
                if (matchOne) {
                        return;
                }
                aword = this.inputStream.read();
                if (aword < 0) {
                        throw new Exception("Connection disconnect...");
                }
                this.buffer.append((char) aword);
        }
}

	private void  getHostConfig(String hostName ) throws Exception {
		if(hostInfo == null){
			JdbcTemplate jdbcTemplat = new JdbcTemplate();
			try{
			hostInfo = jdbcTemplat.queryForMap("select SERVNAME,CNNAME,FTPTYPE,IP,PORT,CHARTSET,WORKDIR,USERNAME,PASSWORD,FILETYPE from DATA_TRANS_FTPSERV where servname='"+hostName+"' and ftptype='ssh'");
			}catch(Exception e){
				meta.log("ERROR","获取服务器{}信息失败。{}",hostName,e.getMessage());
				throw new Exception();
			}
		};		
		if(hostInfo==null||hostInfo.size()==0) {
			meta.log("ERROR","没找到服务器名：{}的配置信息！请检查",hostName);
		}
	}
	
	@Override
	protected int handle() {
		// TODO Auto-generated method stub
		
		String type = meta.getLoginType();
		String hostName=meta.getServerName();
		int result = StepState.RUNNING_SUCCESSED;

		command=meta.getScript();
	    try {
	    	getHostConfig(hostName);
			
	    	if("ssh".equals(type)){
	    		this.connect();
	    		if(channel.getExitStatus()!=0){
	    			meta.log("ERROR","命令:{}返回值不为0.为 {}",command,channel.getExitStatus()+" ");
	    			result=StepState.RUNNING_FAILED;
	    		}else{
	    			meta.log("INFO","命令:{}执行成功",command);
	    		}
	    	}else{
	    		meta.log("ERROR","不支持的连接类型：{}",type);
	    	}
			
		} catch (Exception e) {
			result=StepState.RUNNING_FAILED;
			meta.log("ERROR","连接错误,{}"+e.getMessage());
		}
		 
	    hostInfo=null;
		return result;
	}

	@Override
	public boolean stop() {
		// TODO Auto-generated method stub
		return false;
	}
	
	
	/**
	 * 建立连接
	 * @param hostIp 服务器Ip
	 * @param port   ssh端口号 默认为 22
	 * @param userName
	 * @param password
	 * @throws JSchException 
	 * @throws NumberFormatException 
	 * @throws IOException 
	 */
	public void connect() throws NumberFormatException, JSchException, IOException{
			String charset = "UTF-8"; 
			Properties config = new java.util.Properties(); 
			config.put("StrictHostKeyChecking", "no");
			config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
			session=jsch.getSession(hostInfo.get("username").toString(),hostInfo.get("ip").toString(),Integer.parseInt(hostInfo.get("port").toString()));
			session.setPassword(hostInfo.get("password").toString());
			session.setConfig(config);
			session.connect();
			channel=session.openChannel("exec");//shell、exec、sftp
			((ChannelExec) channel).setCommand(command);
			 channel.setInputStream(null);  
			  ((ChannelExec) channel).setErrStream(System.err);  
			    
			channel.connect();  
			InputStream in = channel.getInputStream();  
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName(charset)));  
			String buf = null;
			//int i=0;
			 while ((buf = reader.readLine()) != null)  
			 {  
				 //System.out.println(buf);
				result+=buf;
			 }  
			 meta.log("INFO",result.toString());
			 meta.getStepState().getReturnValue().put("stepReturn",result);
			 closeSSH();
			 
		
	}
  //关闭连接
	public void  closeSSH(){
       if(null!=channel){
    	   channel.disconnect();
       }
       if(null!=session){
    	   session.disconnect();
       }
	}
	
    public String getResult() throws Exception {
        return getResult(defaultPromt);
    }
    public static void runCmd(String command){
    	//System.out.println(new TelnetProcessor().execute("ls"));
    			String cmd = "date|awk '{print $2,$3,$4}'";
    			//new TelnetProcessor().execute(cmd);
    			Process child = null;
    			try {
    			 
    				Runtime rt = Runtime.getRuntime();
    				child = rt.exec(command);
    				// 以下代码为控制台输出相关的批出理
    				String line = null;
    				
    				int readLine = 0;
    				int loadLine = -1;
    				int commitLine = -1;
    				
    				BufferedReader reader = new BufferedReader(new InputStreamReader(child.getInputStream(),"GBK"));
    				while ((line = reader.readLine()) != null) {
    					System.out.println(line);
    					 
    				};
    				 
    				reader.close();
    				 
    				 
    			} catch (Exception ex) {
    			 
    				System.out.println(ex.getMessage());
    				child.destroy();
    				ex.printStackTrace();
    			 
    			}
    }
    
    //关闭自动登录的session
    public boolean isClosed() {
        return (!(this.client.isConnected()));
    }
    
    /**
     * 关闭连接
     * @throws Exception
     */
    public void close() throws Exception {
            this.client.disconnect();
            meta.log("INFO","断开ftp连接");
    }
    

}
